home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / watchit1.zip / WATCHIT1.ASM < prev    next >
Assembly Source File  |  1990-08-14  |  34KB  |  771 lines

  1.     page 80,132
  2. ;****************************************************************************
  3. ; WATCHCAT copyright 1989, Joseph R. Ahlgren
  4. ;  see WATCHCAT.DOC
  5. ;****************************************************************************
  6. ; WATCHIT1 modification July 29, 1990 Cody Gibson - Added command line
  7. ;  parameters to control the inactivity reset time, and the number of
  8. ;  modem rings reset count.
  9. ;****************************************************************************
  10. ; WATCHIT1 performs 5 critical functions for any BBS system:
  11. ;
  12. ;  1. Reboots system if no carrier detected in specified period of time.
  13. ;     This catches BBS or system failures.
  14. ;
  15. ;  2. Reboots system if carrier is lost during a "critical" period.
  16. ;     This allows Doors to be used safely.
  17. ;
  18. ;  3. Reboots system if too many rings detected without answering phone.
  19. ;     This allows the system to be restarted (rebooted) by phone.
  20. ;
  21. ;  4. Reboots system if "Hit any key to return to system" message appears.
  22. ;     This restarts the system on a common RBBS failure.
  23. ;
  24. ;  5. Drops carrier if L&R shift keys pressed simultaneously.
  25. ;     This allows users to be logged off without a nasty message.
  26. ;
  27. ; WATCHIT1 loads the TSR and disables all functions
  28. ; WATCHIT1 OFF disables all functions
  29. ; WATCHIT1 ON enables 1, 3, 4, and 5
  30. ; WATCHIT1 TIMER enables 2,4,and 5
  31. ;
  32. ;****************************************************************************
  33.  
  34. ;****************************************************************************
  35. LowMem Segment at 0040h            ; BIOS data segment
  36.     Org    0
  37. COM1_Port    dw    ?        ; Location of the COM1 port address
  38.     Org    17h
  39. ShiftStatus    db    ?        ; Location of shift status within BIOS data segment
  40. LowMem    Ends
  41. ;****************************************************************************
  42.  
  43.     .model small
  44.     .code
  45. First    Equ    This Byte
  46.  
  47. ;****************************************************************************
  48. ; Constants
  49. ;****************************************************************************
  50. DOS        Equ    21h        ; DOS functions interrupt
  51. Print        Equ    09h        ; DOS Print string function
  52. Set_Vector    Equ    25h        ; DOS Set interrupt vector function
  53. TSR        Equ    31h        ; DOS Terminate Stay Resident function
  54. Get_Vector    Equ    35h        ; DOS Get interrupt vector function
  55. ;****************************************************************************
  56. IfDef    Debug
  57. Timer_Vector    Equ    61h        ; For debugging only
  58. else
  59. Timer_Vector    Equ    08h        ; Vector number of the 18.2 ticks/second timer
  60. Endif
  61. ModemStatus    Equ    06h        ; Index to Modem Status port
  62. ModemControl    Equ    04h        ; Index to Modem Control port
  63. CarrierDetect    Equ    80h        ; Carrier Detect bit within status byte
  64. RingIndicator    Equ    40h        ; Ring Indicator bit within modem status
  65. TPM        Equ    1092        ; Ticks/Minute = 18.2 * 60
  66. RingTicks    Equ    109        ; Time/phone ring = 6 seconds = 18.2 * 6
  67. ComPort1    Equ    03F8h        ; COM1 base address
  68. ComPort2    Equ    02F8h        ; COM2 base address
  69. ComPort3    Equ    03E8h        ; COM3 base address
  70. ComPort4    Equ    02E8h        ; COM4 base address
  71. ComPort5    Equ    03D8h        ; COM5 base address
  72. ComPort6    Equ    02D8h        ; COM6 base address
  73. ComPort7    Equ    03C8h        ; COM7 base address
  74. ComPort8    Equ    02C8h        ; COM8 base address
  75. ColorScreen    Equ    0B800h        ; Color screen segment address
  76. MonoScreen    Equ    0B000h        ; Mono screen segment address
  77. DropTrigger    Equ    3        ; Drop DTR on L&R shift
  78. NL        Equ    <0Dh,0Ah>    ; Newline definition
  79. ;****************************************************************************
  80.  
  81. ;****************************************************************************
  82. ; The beginning of a .COM file begins at 100h
  83. ;****************************************************************************
  84.     Org    100h
  85. Start:    Jmp    Init
  86. ;****************************************************************************
  87.  
  88. ;****************************************************************************
  89. Ringing        db    0        ; Flag indicating line is ringing
  90. RingLimit    db    4        ; Number of rings required to reboot
  91.                     ;  Default to 4 rings
  92. RingCount    db    0        ; Count of rings received
  93. RingTimer    db    RingTicks    ; Phone ring count down timer (set to 6 seconds)
  94. Flag        db    'F' and 0Fh      ; OFF ON TIME = F N I
  95. TimerInt    dd    ?        ; Original timer interrupt vector
  96. MinReset    dw    6*60        ; Minutes of no carrier to trigger reset
  97.                     ;  Default to 3 hours
  98. Minutes        dw    ?        ; Minutes left before rebooting
  99.                     ;  Default to 3 hours
  100. Seconds        dw    TPM        ; 60 second counter
  101. ColdBoot    dd    0FFFF0000h    ; Address to JMP to perform cold boot
  102. ExitTimer    db    0
  103. ExitMessage    db    'Hit any key to return to system'
  104. ExitMessageSize    Equ    $ - ExitMessage
  105. ComPort        dw    ComPort1    ; Comm port base address
  106.                     ;  default to COM1
  107. ScreenSegment    dw    MonoScreen    ; Screen memory segment address
  108.                     ;  default to mono
  109. Ident        db    "Watchit1 V2.00, (C) 1990 by Joseph R. Ahlgren"
  110. Ident_CRC    dw    0
  111. Signature_Size    Equ    $ - Ident    ; Size of the signature string
  112. PSPSeg        dw    0        ; Our PSP segment address
  113. ;****************************************************************************
  114. ;  This is the captured Timer Interrupt entry point
  115. ;****************************************************************************
  116. Timer    Proc    Near
  117.  
  118.     Assume    DS:Nothing,ES:Nothing,SS:Nothing
  119.     Cmp    CS:[Flag],'F' and 0Fh    ; Have we been turned off?
  120.     Jne    SystemOn        ; no, Check system status
  121. IfDef    Debug
  122.     Iret                ; Simply return in debugging mode
  123. Else
  124.     Jmp    CS:[TimerInt]        ; yes, goto original vector
  125. Endif
  126. ;****************************************************************************
  127. ;  We are enabled, save registers and check system status
  128. ;****************************************************************************
  129. SystemOn:
  130.     Push    AX            ; Save registers
  131.     Push    DX            ;  "
  132.     Push    DS            ;  "
  133.     Push    ES            ;  "
  134. ;****************************************************************************
  135. ; 4. Reboots system if "Hit any key to return to system" message appears
  136. ;    This restarts system on a common RBBS failure
  137. ;****************************************************************************
  138.     Dec    CS:[ExitTimer]        ; Only check condition 4 every 256
  139.                     ;  timer ticks (every 14 seconds)
  140.                     ; Have we reached 256 ticks?
  141.     Jnz    NoExitLoop        ; no, Skip condition 4 check
  142. ;****************************************************************************
  143.                     ; yes, Scan screen for the message
  144.     Push    CX            ; Save registers
  145.     Push    SI            ;  "
  146.     Push    DI            ;  "
  147. ;****************************************************************************
  148.     Mov    AX,CS:[ScreenSegment]    ; Get segment address of the screen
  149.     Mov    DS,AX            ; Point to screen memory
  150.     Mov    AX,CS            ; Point to our own data segment
  151.     Mov    ES,AX            ;  "
  152.     Mov    CX,25            ; Scan 25 lines
  153.     Xor    SI,SI            ; Start at line 0
  154. ;****************************************************************************
  155. SSLoop1:
  156.     Push    CX            ; Save current line count
  157.     Push    SI            ; Save current line address
  158.     Mov    CX,ExitMessageSize    ; Get size of the exit message
  159.     Lea    DI,ExitMessage        ; Point to the exit message to compare against
  160. ;****************************************************************************
  161.     Cld                ; Auto-increment SI & DI
  162. SSLoop2:
  163.     Cmpsb                ; Is the exit message being displayed here?
  164.     Jne    ExitNotFound        ; no, Check the next line
  165.     Inc    SI            ; Skip the attribute byte
  166.     Loop    SSLoop2
  167. ;****************************************************************************
  168.     Jmp    Reboot            ; yes, Reboot the computer!!!
  169. ;****************************************************************************
  170. ExitNotFound:
  171.     Pop    SI            ; Restore line address
  172.     Pop    CX            ; Restore line count
  173.     Add    SI,160            ; Point to the next line
  174.     Loop    SSLoop1            ; Scan all 25 screen lines
  175. ;****************************************************************************
  176.     Pop    DI            ; Restore registers
  177.     Pop    SI            ;  "
  178.     Pop    CX            ;  "
  179. ;****************************************************************************
  180. ; 5. Drops carrier if L&R shift keys pressed simultaneously
  181. ;    This allows users to be logged off without a nasty message.
  182. ;****************************************************************************
  183. NoExitLoop:
  184.     Mov    AX,Lowmem        ; Get address of BIOS data
  185.     Mov    DS,AX            ; Point to BIOS data
  186.     Assume    DS:Lowmem
  187.     Mov    AL,[ShiftStatus]    ; Get current shift state
  188.     And    AL,0Fh            ; Mask off shift state bits
  189.     Cmp    AL,DropTrigger        ; Is the proper shift state set?
  190.     Jne    NoShift            ; no, Check the next condition
  191. ;****************************************************************************
  192.                     ; yes, Drop the link by dropping DTR
  193.     Mov    DX,CS:[ComPort]        ; Get the Comm ports base address
  194.     Add    DX,ModemControl        ; Point to the modem control port
  195.     In    AL,DX            ; Get current state of control lines
  196.     And    AL,0FEh            ; Turn off the DTR line bit
  197.     Out    DX,AL            ; Drop DTR to the modem
  198. ;****************************************************************************
  199. ;  3.  Reboots system if too many rings without answering phone
  200. ;      This allows system to be restarted by phone
  201. ;****************************************************************************
  202. NoShift:
  203.     Mov    DX,CS:[ComPort]        ; Get the Comm ports base address
  204.     Add    DX,ModemStatus        ; Point to the modem status port
  205.     In    AL,DX            ; Get the modems current status
  206.     Test    AL,RingIndicator    ; Is the line ringing?
  207.     Jz    NoRing            ; no, check how long it was ringing
  208. ;****************************************************************************
  209.     Or    CS:[Ringing],1        ; yes, Set ringing indicator
  210. ;****************************************************************************
  211. NoRing:
  212.     Dec    CS:[RingTimer]        ; Ring time expired (6 seconds)?
  213.     Jnz    NoRingTime        ; no, Check condition 2
  214.     Mov    CS:[RingTimer],RingTicks ; yes, reset the ring timer
  215.     Test    CS:[Ringing],1        ; Is the line ringing?
  216.     Jz    NotRinging        ; no, Reset triggers
  217.     Mov    CS:[Ringing],0        ; Reset ringing indicator
  218.     Inc    CS:[RingCount]        ; Count the number of rings
  219.     Mov    AL,CS:[RingCount]    ; Get the ring count
  220.     Cmp    AL,CS:[RingLimit]    ; Have we reached the limit?
  221.     Jb    NoRingTime        ; no, Check condition 2
  222. ;****************************************************************************
  223.     Jmp    Short Reboot        ; yes, reboot machine
  224. ;****************************************************************************
  225. NotRinging:
  226.     Mov    CS:[RingCount],0    ; Ringing stopped, reset ring count
  227. ;****************************************************************************
  228. ; 2. Reboots system if carrier lost during "critical period"
  229. ;    This allows Doors to be used safely
  230. ;****************************************************************************
  231. NoRingTime:
  232.     Cmp    CS:[Flag],'I' and 0Fh    ; Is OFF flag on?
  233.     Jb    NoMonitor        ; yes, Exit and jump to original vector
  234.                     ; Is TIMER flag set?
  235.     Je    TimeCheck        ; yes, 
  236.     In    AL,DX            ; no, ON is set, check for carrier loss
  237.     Test    AL,CarrierDetect    ; Is CD line set?
  238.     Jz    Reboot            ; no, Reboot machine
  239. ;****************************************************************************
  240. NoMonitor:
  241.     Pop    ES            ; Restore registers
  242.     Pop    DS            ;  "
  243.     Pop    DX            ;  "
  244.     Pop    AX            ;  "
  245. IfDef    Debug
  246.     Iret                ; In debug mode, we're not actually
  247.                     ;  attached to the timer interrupt
  248. Else
  249.     Jmp    CS:[TimerInt]        ; Jump to original vector
  250. Endif
  251. ;****************************************************************************
  252. ;  Reboot the computer by jumping directly to the power on reset address
  253. ;****************************************************************************
  254. Reboot:
  255.     Jmp    CS:[ColdBoot]        ; Reboot the computer
  256. ;****************************************************************************
  257. ;  1.  Reboots system if no carrier in specified period of time
  258. ;      This catches BBS or system failures
  259. ;****************************************************************************
  260. TimeCheck:
  261.     Mov    DX,CS:[ComPort]        ; Get the Comm ports base address
  262.     Add    DX,ModemStatus        ; Point to the modem status port
  263.     In    AL,DX            ; Get the modems current status
  264.     Test    AL,CarrierDetect    ; Is CD line set?
  265.     Jnz    ResetTime        ; yes, Reset no carrier timer
  266. ;****************************************************************************
  267.     Dec    CS:[Seconds]        ; Have 60 seconds transpired?
  268.     Jnz    NoMonitor        ; no, Exit and jump to original vector
  269. ;****************************************************************************
  270.     Mov    CS:[Seconds],TPM    ; yes, Reset 60 second counter
  271.     Dec    CS:[Minutes]        ; Minutes count limit reached?
  272.     Jz    Reboot            ; yes, Reboot computer
  273. ;****************************************************************************
  274.     Jmp    Short NoMonitor        ; no, Exit and jump to original vector
  275. ;****************************************************************************
  276. ResetTime:
  277.     Mov    AX,CS:[MinReset]    ; Get minutes count limit
  278.     Mov    CS:[Minutes],AX        ; Set count down timer
  279.     Mov    CS:[Seconds],TPM    ; Reset 60 second counter
  280.     Jmp    Short NoMonitor        ; Exit and jump to original vector
  281.  
  282. Timer    Endp
  283. ;****************************************************************************
  284. ;****************************************************************************
  285. ;  This is the actual start of the module. Control is passed to here upon
  286. ;   loading of the program.
  287. ;****************************************************************************
  288. ;****************************************************************************
  289.     Assume    DS:@Code,ES:@Code,SS:@Code
  290. ;****************************************************************************
  291. Init    Proc    Near
  292.     Mov    AX,CS            ; Point DS to our segment
  293.     Mov    DS,AX            ;  "
  294.     Mov    CS:PSPSeg,ES        ; Save address of our PSP
  295. ;****************************************************************************
  296.     Lea    DX,SignOnMessage    ; Print sign on message
  297.     Mov    AH,Print        ;  "
  298.     Int    DOS            ;  "
  299. ;****************************************************************************
  300. ;  Scan memory to see if we're already loaded
  301. ;****************************************************************************
  302.     Xor    DX,DX            ; Start scanning at segment 0000
  303.     Mov    ES,DX            ;  "
  304.     Mov    BX,CS            ; Make note of our segment
  305. ;****************************************************************************
  306.     Xor    AX,AX            ; Init CRC register
  307.     Lea    SI,Ident        ; Point to signature
  308.     Mov    CX,Signature_Size    ; Get length of signature
  309. CRC:    Shl    AX,1            ; Compute next CRC value
  310.     Adc    AX,0            ; Add the carry bit back in
  311.     Add    AL,[SI]            ; Add in this character into CRC
  312.     Adc    AH,0            ; Add carry into high byte
  313.     Inc    SI            ; Point to next character
  314.     Loop    CRC            ; Loop for all characters
  315.     Mov    Ident_CRC,AX        ; Store computed CRC value
  316. FindLoop:
  317.     Lea    SI,Ident        ; Point to signature
  318.     Mov    DI,SI            ; Copy the address of the signature
  319.     Mov    CX,Signature_Size    ; Get length of signature
  320. Repz    Cmpsb                ; Does this segment contain the signature?
  321.     Jnz    NotQuite        ; no, check next segment
  322.     Jmp    Found            ; yes, found to be already loaded
  323. ;****************************************************************************
  324. NotQuite:
  325.     Inc    DX            ; no, Examine next segment
  326.     Mov    ES,DX            ; Point to next segment
  327.     Cmp    DX,BX            ; Have we reached our own segment?
  328.     Jne    FindLoop        ; no, Continue scanning all memory segments
  329.                     ; yes, Stop scanning, go ahead and load
  330. ;****************************************************************************
  331. ; We're not already loaded. Parse the command line and then load as TSR.
  332. ;****************************************************************************
  333. LoadWatchit1:                ; Watchit1 not found. Go ahead and load as TSR
  334.     Push    DS            ; Save registers
  335. ;***************************************************************************
  336.     Push    ES
  337.     Mov    AX,Lowmem        ; Point to BIOS data area
  338.     Mov    ES,AX            ;  "
  339.     Assume    ES:Lowmem
  340.     Mov    AX,[COM1_Port]        ; Pick up the COM1 port specification
  341.                     ;  and use as the default
  342.     Mov    CS:ComPort,AX        ; Save the port address
  343.     Pop    ES
  344.     Assume    ES:@Code
  345. ;****************************************************************************
  346.     Mov    DS,CS:PSPSeg        ; Get our PSP
  347.     Mov    SI,0080h        ; Offset of command line
  348. ;***************************************************************************
  349.     Lodsb                ; Get length of command line
  350.     Or    AL,AL            ; Check for zero
  351.     Jnz    Cmd_Line_Data        ; Information on command line
  352.     Jmp    Cmd_Line_Exit        ; Nothing on command line
  353. ;***************************************************************************
  354. Cmd_Line_Data:
  355.     Xor    CH,CH            ; Set up count
  356.     Mov    CL,AL            ;  "
  357. ;***************************************************************************
  358. Cmd_Line_Loop:
  359.     Call    Search_String        ; Search for first option
  360.     Or    AL,AL            ; Check return code
  361.     Jz    Cmd_Line_Entry        ; Not string end
  362.     Jmp    Cmd_Line_Exit        ; End of string
  363. ;***************************************************************************
  364. Cmd_Line_Entry:
  365.     Mov    BX,DX            ; Save count
  366.     Add    BX,SI            ; Adjust to next starting location
  367.     Lodsb                ; Get first character
  368.     Dec    DX            ; Reduce string count
  369.     Jnz    Cmd_Line_Code        ; Option has data
  370.     Jmp    Next_Cmd_Option        ; Go to next string
  371. ;***************************************************************************
  372. Cmd_Line_Code:
  373.     Cmp    AL,'-'            ; Check for option identifiers
  374.     Je    Process_Option        ;  "
  375.     Cmp    AL,'/'            ;  "
  376.     Je    Process_Option        ; String is valuid
  377.     Jmp    Next_Cmd_Option        ; Ignore string (not valid)
  378. ;***************************************************************************
  379. Process_Option:
  380.     Lodsb                ; Get next parameter
  381.     Dec    DX            ; Reduce count
  382.     And    AL,0DFh            ; Capitalize byte
  383. ;***************************************************************************
  384.     Cmp    AL,'R'            ; Is it the ring count parameter
  385.     Jne    Not_RC            ; no, Check next option
  386. ;***************************************************************************
  387.     Call    Get_Cmd_Line_Dec    ; Convert ASCII decimal number to hex
  388.     Mov    CS:RingLimit,AL        ; Set the ring limit count
  389.     Jmp    Next_Cmd_Option        ; Next option
  390. ;***************************************************************************
  391. Not_RC:    Cmp    AL,'I'            ; Is it the inactivity time parameter?
  392.     Jne    Not_In            ; no, Check next option
  393. ;***************************************************************************
  394.     Call    Get_Cmd_Line_Dec    ; Convert ASCII decimal number to hex
  395.     Mov    CS:MinReset,AX        ; Set number minutes to timeout
  396.     Jmp    Short Next_Cmd_Option    ; Next option
  397. ;***************************************************************************
  398. Not_In:    Cmp    AL,'S'            ; Is it the screen type indicator?
  399.     Jne    Not_Sc            ; no, Check next option
  400. ;***************************************************************************
  401. Get_Scrn:
  402.     Lodsb                ; Get next parameter
  403.     Dec    DX            ; Reduce count
  404. ;***************************************************************************
  405.     Cmp    AL,':'            ; Skip a ':' character
  406.     Jne    Get_Scrn        ;  "
  407.     Cmp    AL,'='            ; Skip a '=' character
  408.     Jne    Get_Scrn        ;  "
  409. ;***************************************************************************
  410.     And    AL,0DFh            ; Capitalize byte
  411.     Cmp    AL,'C'            ; Is color specified?
  412.     Jne    Not_Color        ; no, Check for mono
  413.     Mov    CS:ScreenSegment,ColorScreen ; Set color screen segment
  414.     Mov    CS:ScreenSegNum,'8'    ; Show B800 as screen segment
  415.     Jmp    Short Next_Cmd_Option    ; Next option
  416. ;***************************************************************************
  417. Not_Color:
  418.     Cmp    AL,'M'            ; Is color specified?
  419.     Jne    Not_Mono        ; no, Check for mono
  420.     Mov    CS:ScreenSegment,MonoScreen ; Set mono screen segment
  421.     Mov    CS:ScreenSegNum,'0'    ; Show B000 as screen segment
  422. ;***************************************************************************
  423. Not_Mono:
  424.     Jmp    Short Next_Cmd_Option    ; Next option
  425. ;***************************************************************************
  426. Not_Sc:
  427.     Cmp    AL,'P'            ; Is it the port parameter?
  428.     Jne    Not_Port        ; no, Check next option
  429. ;***************************************************************************
  430.     Call    Get_Cmd_Line_Hex    ; Convert ASCII decimal number to hex
  431.     Cmp    AX,8            ; Values 1-8 mean COM1-COM8
  432.     Ja    Port_Value        ; Not a COM1-COM8 specification
  433. ;***************************************************************************
  434.     Mov    CS:[ComPortNumber],AL    ; Store the com specification
  435.     Add    CS:[ComPortNumber],'0'    ; Convert to ASCII
  436. ;***************************************************************************
  437.     Cmp    AX,2            ; Values 1-2 can be read from BIOS
  438.     Ja    Not_In_BIOS        ; Greater the COM2 specified
  439.     Push    ES
  440.     Mov    BX,Lowmem        ; Point to BIOS data area
  441.     Mov    ES,BX            ;  "
  442.     Assume    ES:Lowmem
  443.     Mov    BX,AX            ; Copy com number
  444.     Dec    BX            ; Convert to 0-1 range
  445.     Shl    BX,1            ; Convert to word offset
  446.     Mov    AX,ES:[BX]        ; Pick up the com port specification
  447.     Mov    CS:ComPort,AX        ; Save the port address
  448.     Pop    ES
  449.     Assume    ES:@Code
  450. ;***************************************************************************
  451. Port_Value:
  452.     Mov    CS:ComPort,AX
  453.     Jmp    Short Next_Cmd_Option    ; Next option
  454. ;***************************************************************************
  455. Not_In_BIOS:
  456.     Mov    BX,AX            ; Copy com port number
  457.     Dec    BX            ; Convert to 0-7 base
  458.     Shl    BX,1            ; Convert from byte to word offset
  459.     Mov    AX,CS:[ComPorts+BX]    ; Get com port address for this number
  460.     Mov    CS:ComPort,AX        ; Save the port address
  461.     Jmp    Short Next_Cmd_Option    ; Next option
  462. ;***************************************************************************
  463. Not_Port:
  464. ;***************************************************************************
  465. Next_Cmd_Option:
  466.     Mov    SI,BX            ; set next starting location
  467.     JCXZ    Cmd_Line_Exit        ; no more options
  468.     Jmp    Cmd_Line_Loop        ; process next string
  469. ;***************************************************************************
  470. Cmd_Line_Exit:
  471.     Pop    DS            ; restore register
  472. ;***************************************************************************
  473.     Mov    AX,[MinReset]        ; Preset the inactivity minutes counter
  474.     Mov    [Minutes],AX        ;  "
  475. ;****************************************************************************
  476.     Mov    AH,Get_Vector        ; Get timer interrupt vector address
  477.     Mov    AL,Timer_Vector        ;  "
  478.     Int    DOS            ;  "
  479.     Mov    [Word PTR TimerInt],BX    ; Save current vector
  480.     Mov    [Word PTR TimerInt+2],ES ; "
  481. ;****************************************************************************
  482.     Lea    DX,Timer        ; Point to new timer vector
  483.     Mov    AH,Set_Vector        ; Intercept timer interrupt vector
  484.     Mov    AL,Timer_Vector        ; Intercept timer interrupt vector
  485.     Int    DOS            ;  "
  486. ;****************************************************************************
  487.     Lea    DX,Message1        ; Display Loaded message
  488.     Mov    AH,Print        ;  "
  489.     Int    DOS            ;  "
  490. ;****************************************************************************
  491. IfDef    Debug
  492. Infinite_Loop:
  493.     Int    Timer_Vector        ; In debugging mode, execute interrupt
  494.     Jmp    Infinite_Loop        ;  forever to allow for debugging
  495. Else
  496.     Mov    DX,(Init-First+15)/16    ; Amount of memory to keep for TSR
  497.     Mov    AH,TSR            ; TSR
  498.     Mov    AL,01h            ; "
  499.     Int    DOS            ; "
  500. Endif
  501. ;****************************************************************************
  502. ;  WATCHIT1 already found to be resident. Modify the running flags per
  503. ;   request.
  504. ;****************************************************************************
  505. Found:
  506.     Mov    AX,ES            ; Copy segment value
  507.     Lea    DI,Message2x        ; Point to location to store ASCII conversion
  508.     Call    Hex_To_Ascii        ; Convert segment value to ASCII
  509. ;****************************************************************************
  510.     Mov    AX,ES:[MinReset]    ; Reset the inactivity timer
  511.     Mov    ES:[Minutes],AX        ;  "
  512.     Mov    AL,DS:[83h]        ; Fetch second command line letter
  513.     And    AL,0Fh            ; Remove case sensitivity
  514.     Mov    ES:[Flag],AL        ; Save new setting
  515.     Lea    DX,Message2tim        ; Point to "TIMER" message
  516.     Cmp    AL,'I' AND 0Fh        ; Was TIMER set?
  517.     Jz    Done            ; yes, Display message and exit
  518.     Lea    DX,Message2off        ; Point to "OFF" message
  519.                     ; Was OFF set?
  520.     Jb    Done            ; yes, Display message and exit
  521.     Lea    Dx,Message2on        ; Point to "ON" message
  522. Done:
  523.     Push    DX            ; Save pointer to TIMER/OFF/ON message
  524.     Lea    DX,Message2        ; Display "FOUND" message
  525.     Mov    AH,Print        ;  "
  526.     Int    DOS            ;  "
  527.     Pop    DX            ; Restore pointer to TIMER/OFF/ON message
  528.     Mov    AH,Print        ; Display TIMER/OFF/ON message
  529.     Int    DOS            ;  "
  530.     Mov    AX,4C00h        ; Return to DOS with no error code
  531.     Int    DOS            ;  "
  532.     Hlt                ; Should *NEVER* get to here!!!
  533. Init    Endp
  534. ;****************************************************************************
  535. Message1    db    NL,'WATCHIT1 Loaded, set to COM'
  536. ComPortNumber    db    '1 and Screen B'
  537. ScreenSegNum    db    '000.',NL,'$'
  538. Message2    db    0Ah,0Dh,'WATCHIT1 found at '
  539. Message2x    db    '0000 and set to $'
  540. Message2on    db    'ON.',NL,'$'
  541. Message2off    db    'OFF.',NL,'$'
  542. Message2tim    db    'TIMER.',NL,'$'
  543. SignOnMessage    db    NL
  544.         db    'WATCHIT1 V1.00, Copyright 1990 Joseph R. Ahlgren',NL
  545.         db    NL
  546.         db    ' WATCHIT1 may be freely distributed provided this message is not modified',NL
  547.         db    ' Load with WATCHIT1 [/R:NNN][/I:NNNNN][/S:C|M][/P:(1-8)|NNN]',NL
  548.         db    '  where /R is the ring count from 1-255, /I is the Inactivity time limit',NL
  549.         db    '  in minutes from 1-65535, /S is the screen to scan (C for Color, M for Mono)',NL
  550.         db    '  and /P is the COM port to monitor (1-8 or any hex value). The default ring',NL
  551.         db    '  count limit is 4, the default inactivity limit is 360 minutes (6 hours),',NL
  552.         db    '  the default screen is Mono (B000), and the default COM port is COM1 (3F8).',NL
  553.         db    NL
  554.         db    ' Subsequent calls are WATCHIT1 ON, WATCHIT1 OFF, and WATCHIT1 TIMER.',NL
  555.         db    '  OFF disables all functions.',NL
  556.         db    '  ON reboots if carrier lost.',NL
  557.         db    '  TIMER reboots if too many rings without answering phone, if no carrier',NL
  558.         db    '   in hours, or if "Hit any key to return to system" appears on screen.',NL
  559.         db    '   Also, pressing both Left and Right Shift keys simultaneously will',NL
  560.         db    '   drop the line, logging off the current user.',NL
  561.         db    NL
  562.         db    '$'
  563. ;****************************************************************************
  564. ComPorts    dw    ComPort1, ComPort2, ComPort3, ComPort4
  565.         dw    ComPort5, ComPort6, ComPort7, ComPort8
  566. ;****************************************************************************
  567. ; Hex_To_Ascii: This routine will convert a binary number to an ASCII
  568. ;               hexidecimal display, and store the characters in memory.
  569. ;
  570. ;  Inputs:  AX    - Binary number to be converted
  571. ;           DS:DI - Address to store the converted characters at
  572. ;
  573. ;  Outputs: An ASCII string at DS:DI which can be printed to show the value
  574. ;           of the binary number.
  575. ;****************************************************************************
  576. Hex_To_Ascii    Proc    Near
  577.  
  578.     Push    BX            ; Save registers
  579.     Push    CX            ;  "
  580.     Push    DI            ;  "
  581. ;****************************************************************************
  582.     Mov    BX,10h            ; Converting to Ascii Hex display
  583.     Mov    CX,4            ; Number of digits to be converted
  584. ;****************************************************************************
  585. Next_Digit:
  586.     Mul    BX            ; Push next nybble into DL
  587.     Cmp    DL,9            ; Is this digit a number?
  588.     Jbe    Number            ; yes, Convert it to ASCII
  589. ;****************************************************************************
  590.     Add    DL,'A' - '9'        ; no, Add the constant to make it a letter
  591. ;****************************************************************************
  592. Number:
  593.     Add    DL,'0'            ; Add the constant to make it ASCII
  594.     Mov    [DI],DL            ; Store the ASCII character
  595.     Inc    DI            ; Point to the next character location
  596.     Loop    Next_Digit        ; Loop for all digits
  597. ;****************************************************************************
  598.     Pop    DI            ; Restore registers
  599.     Pop    CX            ;  "
  600.     Pop    BX            ;  "
  601.     Ret                ; Return to caller
  602.  
  603. Hex_To_Ascii    Endp
  604. ;***************************************************************************
  605. ;  This routine will search for the first parameter string:
  606. ;    Input:
  607. ;        DS:[SI] -- points to the data area to be searched
  608. ;        CX -- number of bytes to search
  609. ;    Output:
  610. ;        AL -- return code:  00h - parameter
  611. ;                    01h - not found
  612. ;                    02h - terminate on Null (x'00')
  613. ;                    03h - invalid length
  614. ;        DS:[SI] -- points to the string found
  615. ;        CX -- length left
  616. ;        DX -- contains length of string
  617. ;***************************************************************************
  618. Search_String    Proc Near
  619.  
  620.     Or    CX,CX            ; check length
  621.     Jnz    SSLoop            ; start search
  622.     Mov    AL,03h            ; set error code
  623.     Ret                ; return to caller
  624. ;***************************************************************************
  625. SSLoop:
  626.     Lodsb                ; get a byte
  627.     Or    AL,AL            ; test for zero (Null)
  628.     Jz    NullEnd            ; end of string
  629.     Cmp    AL,20h            ; check for blank
  630.     Jne    NonBlank        ; Non-Blank character
  631.     Loop    SSLoop            ; try next character
  632. ;***************************************************************************
  633. EndStr:
  634.     Mov    AL,01h            ; set return code
  635.     Ret                ; return to caller
  636. ;***************************************************************************
  637. NullEnd:
  638.     Mov    AL,02h            ; set return code
  639.     Ret                ; return to caller
  640. ;***************************************************************************
  641. NonBlank:
  642.     Push    SI            ; save index pointer
  643.     Mov    DX,0001h        ; set count register
  644. SSLoopA:
  645.     Lodsb                ; get a byte
  646.     Or    AL,AL            ; test for zero (Null)
  647.     Jz    NonBEnd            ; end of string
  648.     Cmp    AL,0Dh            ; check for CR
  649.     Jz    NonBEnd            ; end of string
  650.     Cmp    AL,' '            ; check for blank
  651.     Jz    NonBEnd            ; end of string
  652.     Cmp    AL,'/'            ; check for slash
  653.     Jz    NonBEnd            ; end of string
  654.     Cmp    AL,'-'            ; check for hyphen
  655.     Je    NonBEnd            ; Non-Blank character
  656.     Inc    DX            ; one more
  657.     Loop    SSLoopA            ; try next character
  658.     Dec    DX            ; back up count one
  659. ;***************************************************************************
  660. NonBEnd:
  661.     Pop    SI            ; restore index
  662.     Dec    SI            ; put si back one
  663.     Xor    AL,AL            ; zero out return code
  664.     Ret                ; return to caller
  665.  
  666. Search_String    Endp
  667. ;***************************************************************************
  668. ;  Get_Cmd_Line_Hex -- This routine will convert an ASCII Hex string
  669. ;            to a Hexidecimal value in AX.
  670. ;    Input:    DS:[SI] -- points to the ASCII Hex string
  671. ;        DX    -- # of bytes in string
  672. ;    Output:    AX    -- Hex value
  673. ;        DS:[SI] -- points to first byte after ASCII Hex string
  674. ;***************************************************************************
  675. Get_Cmd_Line_Hex Proc Near
  676.  
  677.     Push    BX            ; Save registers
  678.     Push    CX            ;    "
  679.     Push    DX            ;    "
  680.     Xor    BX,BX            ; Clear temporary results
  681.     Mov    CL,04h            ; Shift count
  682. ;***************************************************************************
  683.     Cmp    DX,5            ; Maximum # of bytes to process
  684.     Jbe    Cmd_Line_Number_Loop    ; Number of char's is valid
  685.     Mov    DX,5            ; Set maximum number (including a '='
  686.                     ;  character)
  687. ;***************************************************************************
  688. Cmd_Line_Number_Loop:
  689.     Or    DX,DX            ; Any characters left?
  690.     Jz    Cmd_Line_Number_Exit    ; No, exit routine
  691.     Xor    AH,AH            ; Clear high value of work register
  692.     Lodsb                ; Get an ASCII digit
  693.     Dec    DX            ; Decrement character count
  694. ;***************************************************************************
  695.     Cmp    AL,'='            ; Is it simply an '=' character?
  696.     Je    Cmd_Line_Number_Loop    ; yes, Just skip it
  697.     Cmp    AL,':'            ; no, Is it simply an ':' character?
  698.     Je    Cmd_Line_Number_Loop    ; yes, Just skip it
  699. ;***************************************************************************
  700.     Shl    BX,CL            ; Move hex digit to the left
  701.     And    AL,0DFh            ; no, Capitalize the character
  702.     Cmp    AL,'9'            ; Is this a character?
  703.     Jbe    Hex_char_OK        ; no, Skip adjustment
  704.     Sub    AL,07h            ; Adjust value
  705. ;***************************************************************************
  706. Hex_char_OK:
  707.     And    AL,0Fh            ; Save hex number
  708.     Or    BX,AX            ;  "
  709.     Jmp    Cmd_Line_Number_Loop    ;  "
  710. ;***************************************************************************
  711. Cmd_Line_Number_Exit:
  712.     Mov    AX,BX            ; Set return value
  713.     Pop    DX            ; Restore registers
  714.     Pop    CX            ;  "
  715.     Pop    BX            ;  "
  716.     Ret                ; Return to caller
  717.  
  718. Get_Cmd_Line_Hex Endp
  719. ;***************************************************************************
  720. ;  Get_Cmd_Line_Dec -- This routine will convert an ASCII decimal string
  721. ;            to a Hexidecimal value in AX.
  722. ;
  723. ;    Input:    DS:[SI] -- points to the ASCII decimal string
  724. ;        DX    -- # of bytes in string
  725. ;
  726. ;    Output: AX    -- Hex value
  727. ;        DS:[SI] -- points to first byte after ASCII Hex string
  728. ;***************************************************************************
  729. Get_Cmd_Line_Dec Proc Near
  730.  
  731.     Push    BX            ; Save registers
  732.     Push    CX            ;    "
  733.     Push    DX            ;    "
  734.     Xor    BX,BX            ; Clear temporary results
  735.     Mov    CL,10            ; Multiplication factor for next digit
  736. ;***************************************************************************
  737.     Cmp    DX,6            ; Maximum # of bytes to process
  738.     Jbe    Dec_Number_Loop        ; Number of char's is valid
  739.     Mov    DX,6            ; Set maximum number (including a '='
  740.                     ;  character)
  741. ;***************************************************************************
  742. Dec_Number_Loop:
  743.     Or    DX,DX            ; Any characters left?
  744.     Jz    Dec_Number_Exit        ; No, exit routine
  745. ;***************************************************************************
  746.     Xor    AH,AH            ; Clear high value of work register
  747.     Lodsb                ; Get an ASCII digit
  748.     Dec    DX            ; Decrement character count
  749. ;***************************************************************************
  750.     Cmp    AL,'='            ; Is it simply an '=' character?
  751.     Je    Dec_Number_Loop        ; yes, Just skip it
  752.     Cmp    AL,':'            ; no, Is it simply an ':' character?
  753.     Je    Dec_Number_Loop        ; yes, Just skip it
  754. ;***************************************************************************
  755.     Xchg    AX,BX            ; Put value in AX for MUL
  756.     Mul    CL            ; Move digits to the left
  757.     Xchg    BX,AX            ; Save shifted value
  758.     And    AL,0Fh            ; Save decimal number
  759.     Add    BX,AX            ;  "
  760.     Jmp    Dec_Number_Loop        ;  "
  761. ;***************************************************************************
  762. Dec_Number_Exit:
  763.     Mov    AX,BX            ; Set return value
  764.     Pop    DX            ; Restore registers
  765.     Pop    CX            ;  "
  766.     Pop    BX            ;  "
  767.     Ret                ; Return to caller
  768.  
  769. Get_Cmd_Line_Dec Endp
  770.     End    Start
  771.